/**
 * 导入仓库 url方式
 * @param type 默认normal, retry：重新导入
 * @param projectInfo 默认为null，默认数据，在重新导入时用到
 * @param retryCallback 重新导入成功的回调
 */

import React from 'react';
import PropTypes from 'prop-types';
import { Form, Input, Field, Grid, Balloon } from '@teamix/ui';
import { ButtonIcon } from '@alife/devops-ui';
import { ENUM } from 'utils/constants.js';
import exceed from 'utils/apimap';
import AccessSelect from 'components/accessSelect';
import debounce from 'lodash.debounce';
import docs from 'utils/docs';
import { checkProjectName } from 'api/index.js';
import { encrypt } from 'utils/JSEncrypt';
import { navigate, navigateHref } from 'utils/router';
import GroupSelect from 'components/groupSelect';
import AddonBeforeInputSpan from 'components/addonBeforeInput/span';
import intl from '../../../locale';

const FormItem = Form.Item;
const formItemLayout = {
  labelCol: {
    span: 6,
  },

  wrapperCol: {
    span: 14,
  },
};

const { organization } = window.FORCE;

export default class ImportProjectByUrlModal extends React.Component {
  static propTypes = {
    defaultNamespaceId: PropTypes.string,
    trigger: PropTypes.element,
    closeModal: PropTypes.func,
    isModalOpen: PropTypes.bool,
    type: PropTypes.string,
    projectInfo: PropTypes.object,
    retryCallback: PropTypes.func,
  };

  static defaultProps = {
    defaultNamespaceId: '',
    trigger: null,
    closeModal: () => {},
    type: 'normal', // 默认为normal, retry为重新导入
    projectInfo: {
      import_url: '',
      id: '',
    },

    retryCallback: () => {},
  };

  constructor(props) {
    super(props);
    this.field = new Field(this, {
      onChange: (name, value) => {
        if (name === 'namespace_id') {
          this.field.validate();
        }
        if (name === 'import_url' && value && props.type === 'normal') {
          const arr = value.split('/');
          const end = arr.length > 1 ? arr[arr.length - 1] : '';
          const projectName = end.split('.')[0];
          this.field.setValue('name', projectName);
          this.field.setValue('path', projectName);
          this.field.validate();
        }
        if (name === 'name') {
          this.field.setValue('path', value);
          this.field.validate();
        }
      },
    });

    this.state = {
      groupAccess: '',
      // 组的校验是否需要必选校验
      groupSelectRules: [],
      // 聚焦时调整z-index
      namespaceIdFocus: false,
    };

    this.checkPath = debounce(this.checkPath, 500);
    this.checkName = debounce(this.checkName, 500);
  }

  setGroupAccess = (item) => {
    this.setState({
      groupAccess: item.visibility_level,
    });

    this.field.setValue({
      visibility_level: ENUM.visibility_level.PRIVATE,
    });
  };

  checkName(value, callback) {
    let namespace_id = this.field.getValue('namespace_id');
    if (!Number(namespace_id)) {
      namespace_id = organization.namespace_id || '';
    }
    checkProjectName({ name: value, namespace_id })
      .then(() => {
        callback();
      })
      .catch((err) => {
        const errCause = JSON.parse(err.responseText).cause;
        callback(`${errCause}`);
      });
  }

  checkPath(value, callback) {
    let namespace_id = this.field.getValue('namespace_id');
    if (!Number(namespace_id)) {
      namespace_id = organization.namespace_id || '';
    }

    checkProjectName({ path: value, namespace_id })
      .then(() => {
        callback();
      })
      .catch((err) => {
        const errCause = JSON.parse(err.responseText).cause;
        callback(`${errCause}`);
      });
  }

  nameValidator = (rule, value, callback) => {
    if (!value) {
      callback();
      return;
    }
    if (/^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,}$/.test(value)) {
      this.checkName(value, callback);
    } else {
      callback(
        intl.get({
          id: 'code-assets.src.utils.locale.ItCanOnlyContainLetters',
          defaultMessage: "只能包含字母和数字、 '_'、 '.'和'-'，且只能以字母、数字或'_'开头",
        }),
      );
    }
  };

  pathValidator = (rule, value, callback) => {
    if (!value) {
      callback();
      return;
    }
    if (/^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,}$/.test(value)) {
      this.checkPath(value, callback);
    } else {
      callback(
        intl.get({
          id: 'code-assets.src.utils.locale.ItCanOnlyContainLetters',
          defaultMessage: "只能包含字母和数字、 '_'、 '.'和'-'，且只能以字母、数字或'_'开头",
        }),
      );
    }
  };

  gitValidator = (rule, value, callback) => {
    if (!value) {
      callback();
      return;
    }
    if (!/^((https|http|git)?:\/\/)[^\s]+\.git$/.test(value)) {
      callback('代码库地址请以 http:// 或 https:// 开头，以 .git 结尾');
    } else {
      callback();
    }
  };

  setVisibilityLevel = (value) => {
    this.field.setValue('visibility_level', value);

    // 全部禁用时需要提醒
    if (value === '' || value === undefined) {
      this.field.setError(
        'visibility_level',
        intl.get({
          id: 'code-assets.src.utils.locale.ThisParameterIsRequired',
          defaultMessage: '该项为必填项',
        }),
      );
    } else {
      this.field.setError('visibility_level', '');
    }
  };

  handleOk = () => {
    const { projectInfo, type: importType } = this.props;
    const { pathResource } = window.FORCE;
    this.field.validate((errors) => {
      if (!errors) {
        if (this.props.submitting) {
          return;
        }
        this.props.setSubmitting(true);
        const formData = this.field.getValues();
        formData.create_parent_path = true;
        // 重试导入添加参数namespace_id + path
        if (importType === 'retry') {
          formData.namespace_id = pathResource.parentId;
          formData.path = projectInfo.path;
        }
        // 后台需要暂时先写上
        if (!Number(formData.namespace_id)) {
          formData.namespace_id = organization.namespace_id || '';
          formData.create_parent_path = false;
        }
        formData.open_department_id_paths = [];
        if (formData.import_token) {
          formData.import_token_encrypted = 'rsa'; // 使用加密
          formData.import_token = encrypt(formData.import_token, this.props.PUBLIC_KEY);
        } else {
          formData.import_token_encrypted = 'text';
        }

        // 账号编码一下
        if (formData.import_account) {
          formData.import_account = encodeURIComponent(formData.import_account);
        }

        this.formSubmit(formData, (type) => {
          this.props.setSubmitting(false);
          if (type !== 'isFail') {
            this.props.onClose();
          }
        });

        // 描述信息和可见性修改后保存
        if (
          importType === 'retry' &&
          (formData.description !== projectInfo.description ||
            formData.visibility_level !== projectInfo.visibility_level)
        ) {
          this.updateProject({
            ...projectInfo,
            description: formData.description,
            visibility_level: formData.visibility_level,
          });
        }
      }
    });
  };

  updateProject = (data) => {
    exceed
      .fetch({
        api: 'projects.settings.edit',
        params: {
          id: this.props.projectInfo.id,
        },

        data,
      })
      .then(() => {})
      .fail((err) => {
        console.error(err);
      });
  };

  formSubmit = (formData, cb) => {
    const { type, retryCallback } = this.props;
    exceed
      .fetch({
        api: type === 'normal' ? 'projects.post' : 'projects.single.import',
        params: {
          id: this.props.projectInfo.id,
        },

        data: { ...formData, namespace_id: Number(formData.namespace_id) },
      })
      .then((result) => {
        // 错误页面直接跳转
        const isErrorPage = window.ERROR && window.ERROR.errorCode;
        if (isErrorPage) {
          navigateHref(`/${result.path_with_namespace}`);
        } else if (type === 'retry') {
          retryCallback();
        } else {
          navigate(`/${result.path_with_namespace}`, { state: { forceUpdate: true } });
        }

        cb && cb();
      })
      .fail(() => {
        // 接口报错也要回调，以让按钮取消loading状态但是弹窗不关闭
        cb && cb('isFail');
      });
  };

  handleChangeAccess = (value) => {
    this.field.setValue('visibility_level', value);
  };

  setGroupNeedValidate = (isNeed) => {
    this.setState({
      groupSelectRules: isNeed
        ? [
            {
              required: true,
              message: intl.get({
                id: 'code-assets.src.utils.locale.ThisParameterIsRequired',
                defaultMessage: '该项为必填项',
              }),
            },
          ]
        : [],
    });
  };

  render() {
    const { init } = this.field;
    const { groupSelectRules, namespaceIdFocus } = this.state;

    const { type, projectInfo } = this.props;
    const {
      import_url,
      name: projectName,
      visibility_level: curProjectVisibilityLevel,
      description,
      web_url,
    } = projectInfo;
    return (
      <React.Fragment>
        <Form {...formItemLayout} field={this.field} labelAlign="top">
          <FormItem
            label={intl.get({
              id: 'code-assets.importProjectModal.url.SourceCodeLibraryAddress',
              defaultMessage: '源代码库地址',
            })}
            required
          >
            <Input
              autoFocus
              placeholder="请输入 Clone 地址，如 https://XXX.git"
              {...init('import_url', {
                rules: [
                  {
                    required: true,
                    message: intl.get({
                      id: 'code-assets.importProjectModal.url.ThisParameterIsRequired',
                      defaultMessage: '该项为必填项',
                    }),
                  },

                  {
                    validator: this.gitValidator,
                  },
                ],

                initValue: import_url,
              })}
            />
          </FormItem>
          <Grid.Row gutter={20} className="import-url-account-token">
            <Grid.Col span={12}>
              <FormItem
                label={intl.get({
                  id: 'code-assets.importProjectModal.url.Account',
                  defaultMessage: '帐号',
                })}
              >
                <Input
                  placeholder={intl.get({
                    id: 'code-assets.importProjectModal.url.EnterAnAccount',
                    defaultMessage: '请输入帐号',
                  })}
                  {...init('import_account', {
                    // rules: [],
                    initValue: '',
                  })}
                />
              </FormItem>
            </Grid.Col>
            <Grid.Col>
              <FormItem
                label={
                  <span>
                    <span className="before-icon-text">Access Token</span>
                    <Balloon
                      align="t"
                      trigger={
                        <ButtonIcon
                          name="question-line"
                          type="secondary"
                          className="access-token-help"
                        />
                      }
                      type="normal"
                      closable={false}
                    >
                      {intl.get({
                        id: 'code-assets.importProjectModal.url.AccessTokenIsGeneratedFor',
                        defaultMessage: 'Access Token 生成，请参考',
                      })}

                      <a href={docs('accessTokenGenerated')} target="_blank" rel="noreferrer">
                        {intl.get({
                          id: 'code-assets.importProjectModal.url.HelpDocumentation',
                          defaultMessage: '帮助文档',
                        })}
                      </a>
                    </Balloon>
                  </span>
                }
              >
                <Input
                  placeholder={intl.get({
                    id: 'code-assets.importProjectModal.url.SuchAsSfHnp',
                    defaultMessage: '如 67sf7648hnp',
                  })}
                  {...init('import_token', {
                    // rules: [],
                    initValue: '',
                  })}
                />
              </FormItem>
            </Grid.Col>
          </Grid.Row>

          <FormItem
            label={intl.get({
              id: 'code-assets.src.utils.locale.CodeLibraryName',
              defaultMessage: '代码库名称',
            })}
            required
          >
            {type === 'retry' ? (
              <AddonBeforeInputSpan text={projectName} />
            ) : (
              <Input
                spellCheck={false}
                placeholder={intl.get({
                  id: 'code-assets.src.utils.locale.EnterACodeLibraryName',
                  defaultMessage: '请输入代码库名称',
                })}
                {...init('name', {
                  rules: [
                    {
                      required: true,
                      message: intl.get({
                        id: 'code-assets.importProjectModal.url.ThisParameterIsRequired',
                        defaultMessage: '该项为必填项',
                      }),
                    },

                    {
                      validator: this.nameValidator,
                    },
                  ],

                  initValue: projectName,
                })}
              />
            )}
          </FormItem>

          {type === 'retry' ? (
            <FormItem
              label={intl.get({
                id: 'code-assets.importProjectModal.url.CodeLibraryPath',
                defaultMessage: '代码库路径',
              })}
              required
            >
              <AddonBeforeInputSpan text={web_url} />
            </FormItem>
          ) : (
            <div className="import-project-modal-path">
              <FormItem
                label={intl.get({
                  id: 'code-assets.importProjectModal.url.CodeLibraryPath',
                  defaultMessage: '代码库路径',
                })}
                required
                className="origin"
              >
                <AddonBeforeInputSpan
                  text={`${window.location.origin}/${
                    organization.path || organization.organization_id
                  }`}
                />
              </FormItem>
              <FormItem label=" " className={`namespace_id ${namespaceIdFocus ? 'focus' : ''}`}>
                <GroupSelect
                  {...init('namespace_id', {
                    initValue: this.props.defaultNamespaceId || '',
                    rules: groupSelectRules,
                  })}
                  okFn={this.setGroupAccess}
                  style={{ width: '100%' }}
                  operateType={'create'}
                  type={'repo'}
                  setGroupNeedValidate={this.setGroupNeedValidate}
                  popupProps={{
                    align: 'bl tl',
                    needAdjust: false,
                    offset: [0, -4],
                  }}
                  isUsePath
                  popupStyle={{ width: 320 }}
                  autoWidth={false}
                  onFocus={() => {
                    this.setState({
                      namespaceIdFocus: true,
                    });
                  }}
                  onBlur={() => {
                    this.setState({
                      namespaceIdFocus: false,
                    });
                  }}
                />
              </FormItem>
              <FormItem label=" " className="path">
                <Input
                  spellCheck={false}
                  placeholder={intl.get({
                    id: 'code-assets.importProjectModal.url.EnterAPath',
                    defaultMessage: '请输入路径',
                  })}
                  {...init('path', {
                    rules: [
                      {
                        required: true,
                        message: intl.get({
                          id: 'code-assets.src.utils.locale.ThisParameterIsRequired',
                          defaultMessage: '该项为必填项',
                        }),
                      },

                      {
                        validator: this.pathValidator,
                      },
                    ],
                  })}
                />
              </FormItem>
            </div>
          )}

          <FormItem
            label={intl.get({
              id: 'code-assets.src.utils.locale.Description.1',
              defaultMessage: '代码库描述',
            })}
          >
            <Input.TextArea
              placeholder={intl.get({
                id: 'code-assets.src.utils.locale.EnterADescription',
                defaultMessage: '请输入描述',
              })}
              {...init('description', {
                initValue: type === 'retry' ? description : '',
              })}
            />
          </FormItem>
          <FormItem
            required
            className="no-mr-b"
            label={
              <span>
                <span className="before-icon-text">
                  {intl.get({
                    id: 'code-assets.importProjectModal.url.Openness',
                    defaultMessage: '公开性',
                  })}
                </span>
              </span>
            }
          >
            <AccessSelect
              placeholder={intl.get({
                id: 'code-assets.src.utils.locale.SelectPublicity',
                defaultMessage: '请选择公开性',
              })}
              {...init('visibility_level', {
                initValue:
                  type === 'retry' ? curProjectVisibilityLevel : ENUM.visibility_level.PRIVATE,
              })}
              groupAccess={this.state.groupAccess}
              onChange={this.handleChangeAccess}
              initValueFn={this.setVisibilityLevel}
              style={{ width: 270 }}
            />
          </FormItem>
        </Form>
      </React.Fragment>
    );
  }
}
